namespace SimpleWebServices.Web.UI.Html.Validation
{
    using System;
    using System.Text.RegularExpressions;
    using SimpleWebServices;
    using SimpleWebServices.Data;
    using SimpleWebServices.Web.UI.Html.Elements;
    using Xunit;

    public sealed class RegexTextValidatorFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<RegexTextValidator>()
                .DerivesFrom<Validator>()
                .IsConcreteClass()
                .IsUnsealed()
                .HasDefaultConstructor()
                .Result);
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new RegexTextValidator());
        }

        [Fact]
        public void ctor_IInnerElements_Regex()
        {
            Assert.NotNull(new RegexTextValidator(new Label(), new Regex("[^a-zA-Z0-9]")));
        }

        [Fact]
        public void ctor_IInnerElementsNull_Regex()
        {
            Assert.NotNull(new RegexTextValidator(null as IInnerElements, new Regex("[^a-zA-Z0-9]")));
        }

        [Fact]
        public void ctor_IInnerElements_RegexNull()
        {
            Assert.NotNull(new RegexTextValidator(new Label(), null as Regex));
        }

        [Fact]
        public void ctor_IInnerElements_Regex_bool()
        {
            Assert.NotNull(new RegexTextValidator(new Label(), new Regex("[^a-zA-Z0-9]"), true));
        }

        [Fact]
        public void ctor_IInnerElementsNull_Regex_bool()
        {
            Assert.NotNull(new RegexTextValidator(null as IInnerElements, new Regex("[^a-zA-Z0-9]"), true));
        }

        [Fact]
        public void ctor_IInnerElements_RegexNull_bool()
        {
            Assert.NotNull(new RegexTextValidator(new Label(), null as Regex, true));
        }

        [Fact]
        public void prop_IsMatch()
        {
            Assert.True(new PropertyExpectations(typeof(RegexTextValidator).GetProperty("IsMatch"))
                .DefaultValueIs(true)
                .Set(false)
                .Result);
        }

        [Fact]
        public void prop_Regex()
        {
            Assert.True(new PropertyExpectations(typeof(RegexTextValidator).GetProperty("Regex"))
                .IsAutoProperty<Regex>()
                .Result);
        }

        [Fact]
        public void op_Configure_Form_DataCollection()
        {
            string regex = "^[a-zA-Z0-9]+$";

            DataCollection data = new DataCollection();
            data.Add("ErrorText", "Error text");
            data.Add("Display", "display");
            data.Add("IsMatch", "true");
            data.Add("Regex", regex);

            Label label = new Label { Id = "display" };
            Form form = new Form
            {
                Elements = { label }
            };

            RegexTextValidator obj = new RegexTextValidator(null, null, false);
            obj.Configure(form, data);

            Assert.Same(label, obj.Display);
            Assert.Equal<string>("Error text", obj.ErrorText);
            Assert.True(obj.IsMatch);
            Assert.Equal<string>(regex, obj.Regex.ToString());
        }

        [Fact]
        public void op_Configure_Form_DataCollectionEmpty()
        {
            RegexTextValidator obj = new RegexTextValidator(null, null, false);
            obj.Configure(new Form(), new DataCollection());

            Assert.Null(obj.Display);
            Assert.False(obj.IsMatch);
            Assert.Null(obj.Regex);
        }

        [Fact]
        public void op_Configure_Form_DataCollectionNull()
        {
            RegexTextValidator obj = new RegexTextValidator(null, null, false);
            obj.Configure(new Form(), null as DataCollection);

            Assert.Null(obj.Display);
            Assert.False(obj.IsMatch);
            Assert.Null(obj.Regex);
        }

        [Fact]
        public void op_Validate_IElementNotIControl()
        {
            Assert.Throws<ArgumentOutOfRangeException>(() => new RegexTextValidator().Validate(new Anchor()));
        }

        [Fact]
        public void op_Validate_IElementNull()
        {
            Assert.Throws<ArgumentNullException>(() => new RegexTextValidator().Validate(null));
        }

        [Fact]
        public void op_Validate_IElementNullValue()
        {
            string error = "Error text";

            TextInput element = new TextInput
            {
                Value = null
            };

            RegexTextValidator obj = new RegexTextValidator
            {
                Regex = new Regex("^[a-zA-Z0-9]+$"),
                ErrorText = error
            };

            Assert.False(obj.Validate(element));

            Assert.Equal<int>(1, obj.Errors.Count);
            Assert.Equal<string>(error, obj.Errors[0].Description);
        }

        [Fact]
        public void op_Validate_IElementValid()
        {
            TextInput element = new TextInput
            {
                Value = "Abc123"
            };

            RegexTextValidator obj = new RegexTextValidator
            {
                Regex = new Regex("^[a-zA-Z0-9]+$")
            };

            Assert.True(obj.Validate(element));

            Assert.Equal<int>(0, obj.Errors.Count);
        }

        [Fact]
        public void op_Validate_IElementInvalidStringEmpty()
        {
            string error = "Error text";

            TextInput element = new TextInput
            {
                Value = string.Empty
            };

            RegexTextValidator obj = new RegexTextValidator
            {
                Regex = new Regex("^[a-zA-Z0-9]+$"),
                ErrorText = error
            };

            Assert.False(obj.Validate(element));

            Assert.Equal<int>(1, obj.Errors.Count);
            Assert.Equal<string>(error, obj.Errors[0].Description);
        }

        [Fact]
        public void op_Validate_IElementInvalid()
        {
            string error = "Error text";

            TextInput element = new TextInput
            {
                Value = "ABC...123"
            };

            RegexTextValidator obj = new RegexTextValidator
            {
                Regex = new Regex("^[a-zA-Z0-9]+$"),
                ErrorText = error
            };

            Assert.False(obj.Validate(element));

            Assert.Equal<int>(1, obj.Errors.Count);
            Assert.Equal<string>(error, obj.Errors[0].Description);
        }
    }
}